package net.neptech.controller;

import lombok.extern.slf4j.Slf4j;
import net.neptech.entity.vo.dto.KSignalMessage;
import net.neptech.service.FileService;
import net.neptech.utils.StringUtils;
import net.neptech.utils.UploadContext;
import org.apache.tika.Tika;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;
/**
 * 文件上传说明：小文件上传✅，大文件上传✅
 */
@RequestMapping("/storage/fileController")
@RestController
@Slf4j
public class FileController {

    @Autowired
    private FileService fileService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 一个安全上限，避免把整篇 100MB PDF 全塞 Redis：
    private static final int MAX_TEXT_LEN = 200_000; // 约 200KB 纯文本

    @PostMapping("/uploadFileInMeeting")
    public ResponseEntity<Map<String, Object>> uploadFileInMeeting(
            @RequestParam("file") MultipartFile file,
            @RequestParam("conferenceId") String conferenceId,
            @RequestParam("userId") String userId) {
//        这里是假设数据，本来应该是跨模块获取医生信息
        String doctorInfo = "doctorInfo";
        try {
            log.info("收到文件上传请求: conferenceId={}, userId={}, fileName={}",
                    conferenceId, userId, file.getOriginalFilename());
            // 1. 上传 MinIO
            String fileUrl = fileService.uploadFileInMeeting(file, doctorInfo, conferenceId);
            log.info("文件上传成功，访问路径: {}", fileUrl);
            // 2. Kafka 通知（你现有的）
            KSignalMessage kMsg = new KSignalMessage();
            kMsg.setConferenceId(conferenceId);
            kMsg.setFromUserId(userId);
            kMsg.setToUserId("all");
            kMsg.setType("file-shared");
            kMsg.setData(fileUrl);
            String message = com.alibaba.fastjson2.JSON.toJSONString(kMsg);
            kafkaTemplate.send("lxy-signaling-top", message);

            // 3. 从文件中提取文本并写入 Redis
            String key = "meeting:files:" + conferenceId;
            String extracted = tryExtractText(file);
            if (StringUtils.hasText(extracted)) {
                if (extracted.length() > MAX_TEXT_LEN) {
                    extracted = extracted.substring(0, MAX_TEXT_LEN)
                            + "\n\n[...截断，原文过长，已只保留前 " + MAX_TEXT_LEN + " 字节...]";
                }
                redisTemplate.opsForList().rightPush(key, extracted);
            } else {
                String name = (file.getOriginalFilename() == null ? "" : file.getOriginalFilename().toLowerCase());
                if (name.endsWith(".txt") || name.endsWith(".md")) {
                    String content = new String(file.getBytes(), java.nio.charset.StandardCharsets.UTF_8);
                    if (content.length() > MAX_TEXT_LEN) {
                        content = content.substring(0, MAX_TEXT_LEN) +
                                "\n\n[...截断，原文过长，已只保留前 " + MAX_TEXT_LEN + " 字节...]";
                    }
                    redisTemplate.opsForList().rightPush(key, content);
                } else {
                    log.warn("未能提取出文本：{}", file.getOriginalFilename());
                }
            }

            // 4. 返回
            Map<String, Object> response = new HashMap<>();
            response.put("message", "上传成功");
            response.put("fileUrl", fileUrl);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "上传失败", "detail", e.getMessage()));
        }
    }

    // ==== 私有方法：用 Tika 提取文本 ====
    private String tryExtractText(MultipartFile file) {
        try (var in = file.getInputStream()) {
            Tika tika = new Tika();
            // parseToString 会自动识别类型并抽取文本（PDF、Word、PPT、图片 OCR 不支持）
            return tika.parseToString(in);
        } catch (Exception e) {
            log.warn("Tika 提取文本失败: {}", e.getMessage());
            return null;
        }
    }
    // 其他分片方法也类似，可以在 completeUpload 后发送 Kafka 消息
    @PostMapping("/completeUploadInMeeting")
    public ResponseEntity<Map<String, Object>> completeUploadInMeeting(
            @RequestParam("fileId") String fileId,
            @RequestParam("conferenceId") String conferenceId,
            @RequestParam("userId") String userId
    ) {
        try {
            String objectName = fileService.completeUpload(fileId);
            String fileUrl = "/files/" + objectName;
            // 构造消息
            KSignalMessage kMsg = new KSignalMessage();
            kMsg.setConferenceId(conferenceId);
            kMsg.setFromUserId(userId);
            kMsg.setToUserId("all");
            kMsg.setType("file-shared");
            kMsg.setData(fileUrl);
            kafkaTemplate.send("lxy-signaling-top",
                    com.alibaba.fastjson2.JSON.toJSONString(kMsg));
            return ResponseEntity.ok(Map.of(
                    "fileId", fileId,
                    "url", fileUrl,
                    "message", "文件上传并合并成功"
            ));
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "合并失败", "detail", e.getMessage()));
        }
    }
//    @PostMapping("/upload")
//    public String upload(@RequestParam("file") MultipartFile file) {
//        try {
//            fileService.uploadFile(file);  // 调用接口方法
//            return "上传成功";
//        } catch (Exception e) {
//            return "上传失败：" + e.getMessage();
//        }
//    }
    /**
     * 1. 初始化上传
     */
    @PostMapping("/init")
    public ResponseEntity<Map<String, Object>> initUpload(
            @RequestParam("filename") String filename,
            @RequestParam("fileSize") Long fileSize,
            @RequestParam("totalChunks") Integer totalChunks
    ) {
        try {
            UploadContext context = fileService.initUpload(filename, fileSize, totalChunks);

            Map<String, Object> response = new HashMap<>();
            response.put("fileId", context.getFileId());
            response.put("message", "上传已初始化");
            response.put("expireTime", context.getExpireTime());

            return ResponseEntity.ok(response);
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "初始化失败", "detail", e.getMessage()));
        }
    }

    /**
     * 2. 上传分片
     */
    @PostMapping("/chunk")
    public ResponseEntity<Map<String, Object>> uploadChunk(
            @RequestParam("fileId") String fileId,
            @RequestParam("chunkNumber") Integer chunkNumber,
            @RequestParam("chunk") MultipartFile chunk
    ) {
        try {
            boolean success = fileService.uploadChunk(fileId, chunkNumber, chunk);
            if (success) {
                return ResponseEntity.ok(Map.of(
                        "fileId", fileId,
                        "chunkNumber", chunkNumber,
                        "message", "分片上传成功"
                ));
            } else {
                return ResponseEntity.badRequest().body(Map.of("error", "分片上传失败"));
            }
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "上传失败", "detail", e.getMessage()));
        }
    }

    /**
     * 3. 完成上传（合并分片）
     */
    @PostMapping("/complete")
    public ResponseEntity<Map<String, Object>> completeUpload(
            @RequestParam("fileId") String fileId
    ) {
        try {
            String objectName = fileService.completeUpload(fileId);
            return ResponseEntity.ok(Map.of(
                    "fileId", fileId,
                    "objectName", objectName,
                    "url", "/files/" + objectName,  // 假设你有一个静态资源映射
                    "message", "文件上传并合并成功"
            ));
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "合并失败", "detail", e.getMessage()));
        }
    }

    /**
     * 4. 取消上传（清理分片）
     */
    @PostMapping("/abort")
    public ResponseEntity<Map<String, Object>> abortUpload(
            @RequestParam("fileId") String fileId
    ) {
        try {
            fileService.abortUpload(fileId);
            return ResponseEntity.ok(Map.of("fileId", fileId, "message", "上传已取消"));
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(Map.of("error", "取消失败", "detail", e.getMessage()));
        }
    }
}

